#include <ESP8266WiFi.h>
#include "ioMQTT.h"
#include "PubSubClient.h"
#include "ioSerial.h"
#include "ArduinoJson.h"
#include "ESP8266HTTPClient.h"
#include "ioUserSettings.h"
#include "ioMsgHandler.h"

WiFiClient wifi_client;
PubSubClient mqtt_client(wifi_client);
String mqtt_token="";

void callback(char *topic, byte *payload, unsigned int length);

void mqttInit()
{
    DEBUGLN("MQTT Init");
    mqttReconnect();
    mqtt_client.setCallback(callback);
}

/************************************************************************
* 函数名称: getmqttinfo()
* 输入参数: 无
* 返回值  : 无
* 功    能: 获取mqtt设备信息
**********************************************************************/
void getmqttinfo(String token)
{
    HTTPClient http;
    String head = "http://www.gpio.com.cn/iolight/onenet.ashx?cmd=mqttinfo&devid=" + String(ESP.getChipId(), HEX)+"&token="+token;
    Serial.println(head);
    http.begin(head);
    int http_code = http.GET();
    String mqttinfo = http.getString();
    Serial.println(mqttinfo);
    DeserializationError error = deserializeJson(recv_msg_doc, mqttinfo);
    if (error)
    {
        ERRORLN("Failed to parse mqttinfo，please contact your administrator");
    }
    else
    {
        if (recv_msg_doc.containsKey("host"))
        {
            ConfigData["mqtt"] = recv_msg_doc;
            settingsSave();
            if (mqtt_token == "")
            {
                ESP.flashEraseSector(MQTT_ADDR);
                const char *s = ConfigData["mqtt"]["token"];
                ESP.flashWrite((MQTT_ADDR << 12), (uint32_t *)s, 64);
            }
        }
    }
}

/************************************************************************
* 函数名称: mqttReconnect()
* 输入参数: 无
* 返回值  : 无
* 功    能: 链接mqtt
**********************************************************************/
bool mqttReconnect()
{
    bool flag = false;
    if (WiFi.status() == WL_CONNECTED)
    {
        if (ConfigData.containsKey("mqtt"))
        {
            JsonObject mqtt_obj = ConfigData["mqtt"];
            const char *host = mqtt_obj["host"];
            int port = mqtt_obj["port"];
            const char *user = mqtt_obj["user"];
            const char *password = mqtt_obj["password"];
            DEBUGF("token %s\n", password);
            const char *clientid = mqtt_obj["clientId"];
            if (host && port)
            {
                mqtt_client.setServer(host, port);
                DEBUGF("Trying to connect %s:%d\n", host, port);
                if (mqtt_client.connect(clientid, user, password))
                {
                    String sub_topic = String("$creq/#");
                    DEBUGF("MQTT subscribe %s\n", sub_topic.c_str());
                    mqtt_client.subscribe(sub_topic.c_str());
                    flag = true;

                }
            }
            DEBUGF("MQTT state rc = %d\n", mqtt_client.state());
            delay(1000);
        }
        else
        {
            char tok[64];
            ESP.flashRead((MQTT_ADDR << 12), (uint32_t *)tok, 64);
            mqtt_token = "";
            if (tok[0] == 0xff)
            {
                DEBUGF("device token is blank");
            }
            else
            {
                for (uint32_t i = 0; i < 64; i++)
                {
                    if (tok[i] == 0)
                        break;
                    mqtt_token += (char)tok[i];
                }
                Serial.println(mqtt_token);
            }
            getmqttinfo(mqtt_token);
            //连接服务器获取参数
        }
        
      
    }
    return flag;
}

void mqttDisconnect()
{
    mqtt_client.disconnect();
}

void callback(char *topic, byte *payload, unsigned int length)
{
    recv_msg_doc.clear();
    String payload_str = "";
    for (uint32_t i = 0; i < length; i++)
    {
        payload_str += (char)payload[i];
    }
    DeserializationError error = deserializeJson(recv_msg_doc, payload_str);
    if (error)
    {
        DEBUGF("payload:%s", payload_str.c_str());
        ERRORLN("Failed to parse mqtt message");
    }
    else
    {
        msgHandle(&recv_msg_doc, MsgType::udp);
    }
}

bool mqttConnected()
{
    return mqtt_client.connected();
}
extern StaticJsonDocument<1024> udppack;
void mqttPublish_info(void)
{
    char msg[512]={0};
    char tmp[496]={0};
    char d[3];
    if (mqttConnected())
    {
        udppack.clear();

        udppack["version"] = "0.3";
        String m_info_find = ConfigData["name"];
        if (m_info_find != "null")
        {
            udppack["name"] = ConfigData["name"];
        }
        String room = ConfigData["room"];
        if (room != "null")
        {
            udppack["room"] = ConfigData["room"];
        }
        String img = ConfigData["img"];
        if (img != "null")
        {
            udppack["img"] = ConfigData["img"];
        }
        
        serializeJson(udppack, tmp, 496);
        DEBUGF("payload:%s", tmp);
        uint16_t streamLen = strlen(tmp);
        d[0] = '\x03';
        d[1] = (streamLen >> 8);
        d[2] = (streamLen & 0xFF);
        snprintf(msg, sizeof(msg), "%c%c%c%s", d[0], d[1], d[2], tmp);
        mqtt_client.publish("$dp", (uint8_t *)msg, streamLen + 3, false); //上传onenet云的语句
    }
}

void mqttLoop()
{
    static uint8_t infoflag = false;
    mqtt_client.loop();
    if (mqttConnected())
    {
        if (infoflag == false)
        {
            infoflag = true;
            mqttPublish_info();
        }
    }
}

void mqttPublishnum(char *topic, char *ds, uint32 value)
{
    char msg[100];
    char tmp[256];
    char d[3];
    if (mqttConnected())
    {
        snprintf(tmp, sizeof(tmp), "{\"%s\":%d}", ds, value);
        uint16_t streamLen = strlen(tmp);
        d[0] = '\x03';
        d[1] = (streamLen >> 8);
        d[2] = (streamLen & 0xFF);
        snprintf(msg, sizeof(msg), "%c%c%c%s", d[0], d[1], d[2], tmp);
        mqtt_client.publish(topic, (uint8_t *)msg, streamLen + 3, false); //上传onenet云的语句
    }
}



void mqttPublish(char *topic,char *ds,const char *payload)
{
    char msg[100];
    char tmp[256];
    char d[3];
    if (mqttConnected())
    {
        snprintf(tmp, sizeof(tmp), "{\"%s\":\"%s\"}", ds, payload);
        uint16_t streamLen = strlen(tmp);
        d[0] = '\x03';
        d[1] = (streamLen >> 8);
        d[2] = (streamLen & 0xFF);
        snprintf(msg, sizeof(msg), "%c%c%c%s", d[0], d[1], d[2], tmp);
        mqtt_client.publish(topic, (uint8_t *)msg, streamLen + 3, false); //上传onenet云的语句
    }
}

//{"params": {"cmd": "set","file": "new_ac_5227","var": "{\"power\":0,\"temperature\":7,\"mode\":2,\"swing\":1,\"direction\":1,\"speed\":0}"}}
